#include "lua_help.h"
#include <cstdio>
#include <cstring>
#include <cassert>
#include <cstdint>
#include <cmath>
extern "C" {
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}

char const* script1 = R"(
    local val = pow_from_cc(2,5)
    print("pow calc:"..val)
)";

// __cdecl 是函数的调用约定，表示使用 C 语言的默认调用约定
int pow_from_cc(lua_State* state) {
    int param_count = lua_gettop(state);
    if(param_count != 2) {
        return 0;
    }
    if(lua_isinteger(state, 1) && lua_isinteger(state, 2)) {
        auto x = lua_tointeger(state, 1);
        auto y = lua_tointeger(state, 2);
        int rst = (int)pow(x, y);
        lua_pushinteger(state, rst);
        return 1;
    }
    return 0;
}

/**
 * 
 * _G = {
 *     "pow_from_cc" = pow_from_cc;
 * }
 * */

int lua_call_c() {
    lua_State* state = luaL_newstate();
    luaL_openlibs(state); 

    lua_getglobal(state, "_G");
    lua_pushstring(state, "pow_from_cc");
    lua_pushcclosure(state, pow_from_cc, 0); // _G; "pow_from_cc"; closure
    lua_rawset(state, -3); // _G
    lua_pop(state, 1); 
    // nlua_stack_dump(state);

    auto rst = luaL_loadbuffer( state, script1, strlen(script1), "reg_c_closure");
    if(rst != 0) {
        if(lua_isstring(state, -1)) {
            auto msg = lua_tostring(state, -1);
            printf("load script1 failed : %s\n", msg);
            lua_pop(state, 1);
        }
        return -1;
    }
    // 执行chunk
    if(lua_pcall(state, 0, 0, 0)) {
        if(lua_isstring(state, -1)) {
            auto msg = lua_tostring(state, -1);
            printf("call function chunk failed : %s\n", msg);
            lua_pop(state, 1);
        }
    }

    lua_close(state);
    return 0;
}